/*! \file MaterialBuilder.cpp
 *	\brief 
 *
 *	created:	2010/07/14
 *	created:	14:7:2010   12:25
 *	filename: 	C:\src\tactics-engine\libs\gd\MaterialBuilder.cpp
 *	file path:	C:\src\tactics-engine\libs\gd
 *	file base:	MaterialBuilder
 *	file ext:	cpp
 *	author:		Vitalii Trubchaninov
 *				venngraydog@gmail.com
 */
#include "gd/stdafx.h"
#include "gd/MaterialBuilder.h"

#include <core/Format.h>
#include <gd/Device.h>
#include <gd/Material.h>
#include <gd/ShaderBuilder.h>
#include <io/BaseIStream.h>
#include <resource_manager/ResourceManager.h>
#include <utils/PTree.h>

namespace tt{
namespace gd{

namespace impl{

//////////////////////////////////////////////////////////////////////////
class MaterialBuilderImpl
{
public:
	MaterialBuilderImpl(const SharedPtr<Device>& device);

	SharedPtr<Material> createMaterial(const String& fileName);

private:
	SharedPtr<PixelShader> createPixelShader(const SharedPtr<utils::PTree>& materialDesc);
	SharedPtr<VertexShader> createVertexShader(const SharedPtr<utils::PTree>& materialDesc);

private:
	SharedPtr<gd::ShaderBuilder> m_shaderBuilder;
};

MaterialBuilderImpl::MaterialBuilderImpl( const SharedPtr<Device>& device )
: m_shaderBuilder( device->createShaderBuilder() )
{
}

SharedPtr<Material> MaterialBuilderImpl::createMaterial( const String& fileName )
{
	SharedPtr<io::BaseIStream> is = ttResourceManager().GetStream(fileName);
	if(!is)
		ttThrow( str( Format("File not found %1%") % fileName ) );

	SharedPtr<utils::PTree> materialDesc(new utils::PTree);
	utils::read_xml(*is, *materialDesc);

	SharedPtr<gd::VertexShader> vertexShader = createVertexShader(materialDesc);
	if(!vertexShader)
		return SharedPtr<Material>();

	SharedPtr<gd::PixelShader> pixelShader = createPixelShader(materialDesc);
	if(!pixelShader)
		return SharedPtr<Material>();

	SharedPtr<Material> material(new Material);
	material->setShaders(pixelShader, vertexShader);

	return material;
}

SharedPtr<gd::PixelShader> MaterialBuilderImpl::createPixelShader(const SharedPtr<utils::PTree>& materialDesc)
{
	const utils::PTree& pixelShaderChild = materialDesc->get_child("Material.PixelShader");
	return m_shaderBuilder->createPixelShader(pixelShaderChild);
}

SharedPtr<gd::VertexShader> MaterialBuilderImpl::createVertexShader(const SharedPtr<utils::PTree>& materialDesc)
{
	const utils::PTree& vertexShaderChild = materialDesc->get_child("Material.VertexShader");
	return m_shaderBuilder->createVertexShader(vertexShaderChild);
}

} //namespace impl

//////////////////////////////////////////////////////////////////////////
MaterialBuilder::MaterialBuilder(const SharedPtr<Device>& device)
: m_device(device)
{

}

MaterialBuilder::~MaterialBuilder()
{

}

SharedPtr<Material> MaterialBuilder::createMaterial( const String& fileName )
{
	impl::MaterialBuilderImpl impl(m_device);
	return impl.createMaterial(fileName);
}

} //namespace gd
} //namespace tt

